1. /* sdfrcbrt.cpp by K.Tsuru */
  2. // function ID 3011 DRADIX only
  3. /*****************************************************************
  4. SDouble class
  5. reciprocal cubic root of x
  6. [Algorithm]
  7. Get a solusion of an equation 1/(x^3) - a = 0 by the
  8. Newton's method with "doubling effective figures"(DEF).
  9. See Sqrt() for detail.
  10. Let d(n) = {x(n) - a*x(n)^4}/3 ... faster than x(n){1-a*x(n)^3}/3
  11. x(n+1) = x(n) + d(n)
  12. ******************************************************************/
  13. #ifndef SN_H
  14. #include "sn.h"
  15. #endif
  16. static const char* const func = "RecCbrt";
  17. SDouble RecCbrt(const SDouble& a){
  18. if(a.Type() != a.REAL) a.SetError(a.RADIX_ERR, func, 3011);
  19. if(a.Sign() == 0) a.SetError(a.DIVIDED_BY_ZERO, func, 3011);
  20. RealSize C;
  21. uint max_sz = a.MaxSize();
  22. SDouble w(Dabs(a)), one(1.0);
  23. double w0;
  24. if(a.IsOne()){ // |a| = 1.0
  25. if(a.Sign() < 0) one.ChangeSign();
  26. return one;
  27. }
  28. int e = w.NetRdxExp(), q, r, pow10 = 0;
  29. // a = d*R^e = (d*R^q)*R^(3*r) , e = q + 3r
  30. r = e/3;
  31. q = 3*r;
  32. if(e - q > 0){ r++; q += 3; }
  33. w.MultPowRdx(-q); // Here 1/R^3 <= w < 1.0.
  34. /*set an initial value y0*/
  35. w0 = doubleD(w);
  36. while(w0 < 1.0e-3){ // 0.001 <= w0 < 1.0
  37. w0 *= 1000.0; pow10++;
  38. }
  39. if(pow10) w.MultPow10(3*pow10);
  40. //enter the irreducible size mode
  41. SDouble y(a.REAL, max_sz), delta(a.REAL, max_sz), z(a.REAL, max_sz);
  42. y = pow(w0, -1.0/3.0); // y has about DOUBLE_FIG figures.
  43. /***************************************************************/
  44. int c = 0, itrmax = howpow2( (DFIGURES*max_sz)/DOUBLE_FIG+1 ) +6;
  45. uint ef = (DOUBLE_FIG*2u)/DFIGURES, fig = C.EffFigures();
  46. int fullPrec = 0;
  47. delta = w0 - w;
  48. if( delta.Sign() ){
  49. // If w0 is very close to double value, higher precision is necessary.
  50. ef = max( ef, 2u*(uint)abs( delta.NetRdxExp()) );
  51. }
  52. //enter fiexd point mode
  53. y.FixedPoint(y.RdxExp());
  54. if(ef > fig) ef = fig;
  55. do{
  56. if( (ef = C.SetEffFig(ef)) >= fig) fullPrec = 1;
  57. z = y*y; z = z*z; // z = y^4
  58. delta = y - w*z;
  59. delta = DsDiv(delta, 3); // delta /= 3
  60. y += delta;
  61. c++;
  62. ef *= 2;
  63. if(ef >= fig) ef = fig;
  64. C.SetEffFig(0);
  65. } while( ( !delta.IsHidden() && (c < itrmax) ) || !fullPrec );
  66. y.iterationCount = c;
  67. #ifndef NDEBUG
  68. if(c == itrmax) y.SetError(y.FATAL, func, 3011);
  69. #endif
  70. y.PointFree();
  71. y.Reform(3011);
  72. /*******************************************************************
  73. [Reference]
  74. A revision may not be necessary.
  75. Let d = 1/(y'^3) - w.
  76. If d != 0
  77. y = w^(-1/3) = {1/(y'^3) -d}^(-1/3) ~= y'{1 + d*(y'^3)}/3
  78. = y' + (y'^4)*d/3.
  79. ********************************************************************/
  80. #if 0
  81. if(y.PreferSpeed() == OFF){
  82. delta = Dpow(y, -3) - w; //Almost 'delta' has only one figure.
  83. if(delta.Sign()){
  84. z = y*y; z = z*z; // z=y^4
  85. delta = delta*z;
  86. y += DsDiv(delta, 3);
  87. }
  88. }
  89. #endif
  90. if(y.Verify()){
  91. z = y*y; z *= y; // z =y^3
  92. delta = one - z*w; // delta = 1 - w*y^3
  93. if(!delta.IsMLT(w)){
  94. y.SetError(y.VERIFY, func, 3011);
  95. }
  96. }
  97. if(r) y.MultPowRdx(-r);
  98. if(pow10) y.MultPow10(pow10);
  99. if(a.Sign() < 0) y.ChangeSign();
  100. return y;
  101. }

sdfrcbrt.cpp : last modifiled at 2007/11/01 13:23:02(3,113 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).